package sivan.test;

import java.util.concurrent.locks.LockSupport;

/**
 * 线程interrupt的影响：对于不用状态下的线程，发生中断影响不一样。
 * 主要针对阻塞状态调用可以解脱线程继续执行
 */
public class ThreadDemo {

    /**
     * Thread.sleep() 和 Object.wait() 区别
     * 1 Thread.sleep()不会释放占有的锁，Object.wait()会释放占有的锁；
     * 2 Thread.sleep()必须传入时间，Object.wait()可传可不传，不传表示一直阻塞下去；
     * 3 Thread.sleep()到了指定时间会自动唤醒并继续执行
     * 4 Object.wait()不带时间的，需要另一个线程使用Object.notify()唤醒；
     * Object.wait()带时间的，假如没有被notify，到时间了会自动唤醒，这时又分好两种情况，
     * 一是立即获取到了锁，线程自然会继续执行；二是没有立即获取锁，线程进入同步队列等待获取锁；
     */

    /**
     *Thread.sleep()和LockSupport.park()的区别
     * 1 从功能上来说，Thread.sleep()和LockSupport.park()方法类似，
     * 都是阻塞当前线程的执行，且都不会释放当前线程占有的锁资源；
     * 2 Thread.sleep()没法从外部唤醒，只能自己醒过来。
     *   LockSupport.park()方法可以被另一个线程调用LockSupport.unpark()方法唤醒；
     * 3 Thread.sleep()方法声明上抛出了InterruptedException中断异常，
     * 所以调用者需要捕获这个异常或者再抛出；LockSupport.park()不用捕获异常
     * 4 interrupt中断会停止阻塞并抛出异常继续进行。
     */

    /**
     * Object.wait()和LockSupport.park()的区别
     * 二者都会阻塞当前线程的运行
     * （1）Object.wait()方法需要在synchronized块中执行；
     * （2）LockSupport.park()可以在任意地方执行；
     * （3）Object.wait()方法声明抛出了中断异常，调用者需要捕获或者再抛出；LockSupport.park()不需要捕获中断异常；
     * （4）Object.wait()不带超时的，需要另一个线程执行notify()来唤醒，但不一定继续执行后续内容；
     * （5）LockSupport.park()不带超时的，需要另一个线程执行unpark()来唤醒，一定会继续执行后续内容；
     * （6）如果在wait()之前执行了notify()会怎样？抛出IllegalMonitorStateException异常；
     * （8）如果在park()之前执行了unpark()会怎样？线程不会被阻塞，直接跳过park()，继续执行后续内容；
     */

    public static class MyThread extends Thread {

        private final Object object;

        public MyThread(Object object) {
            this.object = object;
        }

        @Override
        public void run() {
            synchronized (object) {
                System.out.println(Thread.currentThread().getName() + "正在执行");
                try {
                    object.wait();//获取锁才能调用wait，使用
                } catch (InterruptedException e) {
                    System.out.println(Thread.currentThread().getName() + "出现中断异常");
                }

//                LockSupport.park(); //线程堵塞，不会释放锁资资源，中断会unpark
                System.out.println(Thread.currentThread().getName() + "继续操作");
            }
        }
    }


    public static class ParkThread extends Thread {

        int i = 0;


        public ParkThread(String name, int i) {
            super(name);
            this.i = i;
        }

        @Override
        public void run() {
            System.out.println(Thread.currentThread().getName() + "=============");
            LockSupport.park();
            System.out.println(Thread.currentThread().getName() + "在运行--------");
            super.run();
        }
    }

    /**
     * notify()和notifyAll()唤醒该对象等待池里面的线程进入锁池。
     *
     * @param object
     */
    public static void myNotify(Object object) {
        synchronized (object) {
            object.notify();
        }
    }

    public static void main(String[] args) throws InterruptedException {
        Object object = new Object();
        MyThread t1 = new MyThread(object);
        t1.start();

        MyThread t2 = new MyThread(object);
        t2.start();

        MyThread t3 = new MyThread(object);
        t3.start();

        t3.interrupt();
        System.out.println("t1的状态：" + t1.getState());
        System.out.println("t2的状态：" + t2.getState());
        System.out.println("t3的状态：" + t3.getState());

        Thread t4 = new ParkThread("parkThread", 1);
        t4.start();

        Thread.sleep(300);
        LockSupport.unpark(t4);
        System.out.println("=======" + Thread.interrupted());
    }
}
